﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HexChessBoard.PlayerComponents;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Input;

namespace HexChessBoard
{
    public struct Move
    {
        // Movement and piece info.
        public PieceType SourceTilePiece;
        public PieceColor SourceTileSide;
        public int SourceTileIndex;
        public int DestTileIndex;

        // CAPTURE: these can be null or none, replace attacked pieces if direct attack. Always opposite side of source side.
        public PieceType DestTilePiece;
        // CAPTURE: Enpassant variables, replace if necessary. Always a pawn of the opposite side of source side.
        public bool WasEnPassant;
        public int EnPassantIndex;
        // PIECE:
        public bool SourceTilePieceHasMoved;
        public bool SourceTilePieceWasPawnOnStartingTile;
        // BOARD: variables
        public short BoardRepeatCount;
        public short BoardFiftyMoveCount;
        public int Score;

        public Move(PieceType p_SourceTilePiece, PieceColor p_SourceTileSide, int p_SourceTileIndex, int p_DestTileIndex, PieceType p_DestTilePiece,
                bool p_WasEnPassant, int p_EnPassantIndex, bool p_SourceTilePieceHasMoved, bool p_SourceTilePieceWasPawnOnStartingTile, 
                short p_BoardRepeatCount, short p_BoardFiftyMoveCount, int p_Score)
        {
            SourceTilePiece = p_SourceTilePiece;
            SourceTileSide = p_SourceTileSide;
            SourceTileIndex = p_SourceTileIndex;
            DestTileIndex = p_DestTileIndex;
            DestTilePiece = p_DestTilePiece;
            WasEnPassant = p_WasEnPassant;
            EnPassantIndex = p_EnPassantIndex;
            SourceTilePieceHasMoved = p_SourceTilePieceHasMoved;
            SourceTilePieceWasPawnOnStartingTile = p_SourceTilePieceWasPawnOnStartingTile;
            BoardRepeatCount = p_BoardRepeatCount;
            BoardFiftyMoveCount = p_BoardFiftyMoveCount;
            Score = p_Score;
        }
    }

   /// <summary>
    /// The hexagonal chess board, comprised of 91 tiles, defined in FileRank notation.
    /// </summary>
    /// TODO make drawable game component and remove draw/update calls
    sealed public class Board
    {
        private SpriteFont spriteFont, spriteFontMed, spriteFontSmall;
        private float thinkingFade;
        public SoundEffect moveSound, captureSound, timerSound, endSound, checkSound;
        private Texture2D ai, gradient, aButton, bButton, xButton, yButton, leftShoulder, rightShoulder;
        private Texture2D pawnWhiteTex, pawnBlackTex, rookWhiteTex, rookBlackTex, knightWhiteTex, knightBlackTex, bishopWhiteTex, bishopBlackTex,
            queenWhiteTex, queenBlackTex, kingWhiteTex, kingBlackTex, kingWhiteCheckTex, kingBlackCheckTex, kingWhiteCheckmateTex, kingBlackCheckmateTex;
        private Model tileDark, tileLight, tileGrey, containerWhite, containerBlack, starWhite, starBlack, diamondWhite, diamondBlack;
        private Model pawnWhite, pawnBlack, rookWhite, rookBlack, knightWhite, knightBlack, bishopWhite, bishopBlack, queenWhite, queenBlack, kingWhite, kingBlack;
        private Matrix[] tileDarkTransforms, tileLightTransforms, tileGrayTransforms, containerWhiteTransforms, containerBlackTransforms, 
            starWhiteTransforms, starBlackTransforms, diamondWhiteTransforms, diamondBlackTransforms;
        private Matrix[] pawnWhiteTransforms, pawnBlackTransforms, rookWhiteTransforms, rookBlackTransforms, knightWhiteTransforms, knightBlackTransforms,
            bishopWhiteTransforms, bishopBlackTransforms, queenWhiteTransforms, queenBlackTransforms, kingWhiteTransforms, kingBlackTransforms;
        private Vector3 tileColorMoveable = new Vector3(0.0f, 0.8f, 0.0f);
        private Vector3 tileColorAttackable = new Vector3(0.8f, 0.0f, 0.0f);
        private Vector3 pieceColor = new Vector3(0.2f, 0.2f, 0.2f);
        private Vector3 selectedColor = new Vector3(0.0f, 0.5f, 0.0f);
        private Vector3 attackableColor = new Vector3(0.5f, 0.0f, 0.0f);
        private Vector3 currentColor;

        Player curPlayer = null;
        private GameVariant variant;
        public GameVariant Variant
        {
            get { return variant; }
        }
        private Tile[] tiles;
        public Tile[] Tiles
        {
            get { return tiles; }
        }
        public int numPlayers;
        public PieceColor player1Color;
        private bool isPlayer2AI;
        public bool isAIThinking = false;
        private Player[] players;
        public Difficulty difficulty;

        public PieceColor CurrentTurn = PieceColor.White;

        public List<Move> Moves;
        public List<PieceType> WhitePiecesDead = new List<PieceType>();
        public List<PieceType> BlackPiecesDead = new List<PieceType>();
        public int WhiteKing;
        public int BlackKing;

        // 0 = can't castle, 1 = can castle short, 2 = can castle long
        public short CanCastleWhiteBishop = 0;
        public short CanCastleWhiteQueen = 0;
        public short CanCastleBlackBishop = 0;
        public short CanCastleBlackQueen = 0;

        public int Score = 0;

        public bool WhiteCheck = false;
        public bool BlackCheck = false;
        public bool WhiteCheckmate = false;
        public bool BlackCheckmate = false;
        public bool Stalemate = false;
        public short WhiteRepeatedMoveCount = 0;
        public List<string> BoardPositions = new List<string>();    // the list of board positions so far in the game, for tracking repeated move count
        public short RepeatedMoveCount = 0;
        public short FiftyMoveCount = 0;

        // This is used to track and display opposing units move for draws.
        public List<int> OpposingMoves = new List<int>();

        /// <summary>
        /// Construct a brand new board with a specified variant.
        /// </summary>
        /// <param name="p_Variant"></param>
        public Board(ContentManager content, GameVariant p_Variant, Difficulty p_difficulty, int p_NumPlayers, PieceColor p_Player1Color, Vector2 screenSize, Viewport viewport, PlayerIndex[] playerIndices)
        {
            // Lists
            Moves = new List<Move>(128);

            // Initialize the variables, table is by default all null
            difficulty = p_difficulty;
            player1Color = p_Player1Color;
            variant = p_Variant;

            switch (variant)
            {
                case GameVariant.Glinsky:
                case GameVariant.McCooey:
                    BoardConstructor.ConstructTilesGlinskiMcCooey(ref tiles);
                    break;
                case GameVariant.Shafran:
                    BoardConstructor.ConstructTilesShafran(ref tiles);
                    break;
            }

            // Place pieces dependant on the variant
            switch (variant)
            {
                case GameVariant.Glinsky:
                    BoardConstructor.PlaceGlinksi(ref tiles);
                    WhiteKing = 51;
                    BlackKing = 60;
                    break;
                case GameVariant.McCooey:
                    BoardConstructor.PlaceMcCooey(ref tiles);
                    WhiteKing = 51;
                    BlackKing = 60;
                    break;
                case GameVariant.Shafran:
                    BoardConstructor.PlaceShafran(ref tiles);
                    WhiteKing = 30;
                    BlackKing = 39;
                    break;
            }
            BoardConstructor.PlaceModelPositions(ref tiles, this.variant);

            // Construct moveable/attackable tiles. Only need to look at the first color.
            BoardSupport.GetAllSideAvailableMoves(this, PieceColor.White, true);

            // Initialize the players
            numPlayers = p_NumPlayers;
            players = new Player[2];
            players[0] = new PlayerLocal(playerIndices[0], p_Player1Color, this, screenSize, viewport);

            if (p_NumPlayers == 1)
            {
                players[1] = new PlayerAI(this, p_Player1Color == PieceColor.White ? PieceColor.Black : PieceColor.White);
                isPlayer2AI = true;
            }
            else
            {
                players[1] = new PlayerLocal(playerIndices[1], p_Player1Color == PieceColor.White ? PieceColor.Black : PieceColor.White, this, screenSize, viewport);
                isPlayer2AI = false;
            }

            // TODO move to LoadComponents
            // Load models
            tileDark = content.Load<Model>("Models/hex_dark");
            tileLight = content.Load<Model>("Models/hex_light");
            tileGrey = content.Load<Model>("Models/hex_grey");
            containerWhite = content.Load<Model>("Models/container_white");
            containerBlack = content.Load<Model>("Models/container_black");
            diamondWhite = content.Load<Model>("Models/diamond_white");
            diamondBlack = content.Load<Model>("Models/diamond_black");
            starWhite = content.Load<Model>("Models/star_white");
            starBlack = content.Load<Model>("Models/star_black");
            pawnWhite = content.Load<Model>("Models/pawn_white");
            pawnBlack = content.Load<Model>("Models/pawn_black");
            rookWhite = content.Load<Model>("Models/rook_white");
            rookBlack = content.Load<Model>("Models/rook_black");
            knightWhite = content.Load<Model>("Models/knight_white");
            knightBlack = content.Load<Model>("Models/knight_black");
            bishopWhite = content.Load<Model>("Models/bishop_white");
            bishopBlack = content.Load<Model>("Models/bishop_black");
            queenWhite = content.Load<Model>("Models/queen_white");
            queenBlack = content.Load<Model>("Models/queen_black");
            kingWhite = content.Load<Model>("Models/king_white");
            kingBlack = content.Load<Model>("Models/king_black");

            // CopyTransforms
            tileDarkTransforms = new Matrix[tileDark.Bones.Count];
            tileLightTransforms = new Matrix[tileLight.Bones.Count];
            tileGrayTransforms = new Matrix[tileGrey.Bones.Count];
            containerWhiteTransforms = new Matrix[containerWhite.Bones.Count];
            containerBlackTransforms = new Matrix[containerBlack.Bones.Count];
            diamondWhiteTransforms = new Matrix[diamondWhite.Bones.Count];
            diamondBlackTransforms = new Matrix[diamondBlack.Bones.Count];
            starWhiteTransforms = new Matrix[starWhite.Bones.Count];
            starBlackTransforms = new Matrix[starBlack.Bones.Count];
            pawnWhiteTransforms = new Matrix[pawnWhite.Bones.Count];
            pawnBlackTransforms = new Matrix[pawnBlack.Bones.Count];
            rookWhiteTransforms = new Matrix[rookWhite.Bones.Count];
            rookBlackTransforms = new Matrix[rookBlack.Bones.Count];
            knightWhiteTransforms = new Matrix[knightWhite.Bones.Count];
            knightBlackTransforms = new Matrix[knightBlack.Bones.Count];
            bishopWhiteTransforms = new Matrix[bishopWhite.Bones.Count];
            bishopBlackTransforms = new Matrix[bishopBlack.Bones.Count];
            queenWhiteTransforms = new Matrix[queenWhite.Bones.Count];
            queenBlackTransforms = new Matrix[queenBlack.Bones.Count];
            kingWhiteTransforms = new Matrix[kingWhite.Bones.Count];
            kingBlackTransforms = new Matrix[kingBlack.Bones.Count];

            tileDark.CopyAbsoluteBoneTransformsTo(tileDarkTransforms);
            tileLight.CopyAbsoluteBoneTransformsTo(tileLightTransforms);
            tileGrey.CopyAbsoluteBoneTransformsTo(tileGrayTransforms);
            containerWhite.CopyAbsoluteBoneTransformsTo(containerWhiteTransforms);
            containerBlack.CopyAbsoluteBoneTransformsTo(containerBlackTransforms);
            diamondWhite.CopyAbsoluteBoneTransformsTo(diamondWhiteTransforms);
            diamondBlack.CopyAbsoluteBoneTransformsTo(diamondBlackTransforms);
            starWhite.CopyAbsoluteBoneTransformsTo(starWhiteTransforms);
            starBlack.CopyAbsoluteBoneTransformsTo(starBlackTransforms);
            pawnWhite.CopyAbsoluteBoneTransformsTo(pawnWhiteTransforms);
            pawnBlack.CopyAbsoluteBoneTransformsTo(pawnBlackTransforms);
            rookWhite.CopyAbsoluteBoneTransformsTo(rookWhiteTransforms);
            rookBlack.CopyAbsoluteBoneTransformsTo(rookBlackTransforms);
            knightWhite.CopyAbsoluteBoneTransformsTo(knightWhiteTransforms);
            knightBlack.CopyAbsoluteBoneTransformsTo(knightBlackTransforms);
            bishopWhite.CopyAbsoluteBoneTransformsTo(bishopWhiteTransforms);
            bishopBlack.CopyAbsoluteBoneTransformsTo(bishopBlackTransforms);
            queenWhite.CopyAbsoluteBoneTransformsTo(queenWhiteTransforms);
            queenBlack.CopyAbsoluteBoneTransformsTo(queenBlackTransforms);
            kingWhite.CopyAbsoluteBoneTransformsTo(kingWhiteTransforms);
            kingBlack.CopyAbsoluteBoneTransformsTo(kingBlackTransforms);

            // Load fonts
            spriteFont = content.Load<SpriteFont>("Fonts/gamefont");
            spriteFontMed = content.Load<SpriteFont>("Fonts/gamefontMed");
            spriteFontSmall = content.Load<SpriteFont>("Fonts/gamefontSmall");

            // Load sounds
            moveSound = content.Load<SoundEffect>("Sounds/move");
            captureSound = content.Load<SoundEffect>("Sounds/capture");
            endSound = content.Load<SoundEffect>("Sounds/end");
            timerSound = content.Load<SoundEffect>("Sounds/timer");
            checkSound = content.Load<SoundEffect>("Sounds/check");

            // Load Textures
            ai = content.Load<Texture2D>("Textures/ai");
            gradient = content.Load<Texture2D>("Textures/ScreenManagement/gradient");
            aButton = content.Load<Texture2D>("Textures/xboxControllerButtonA");
            bButton = content.Load<Texture2D>("Textures/xboxControllerButtonB");
            xButton = content.Load<Texture2D>("Textures/xboxControllerButtonX");
            yButton = content.Load<Texture2D>("Textures/xboxControllerButtonY");
            leftShoulder = content.Load<Texture2D>("Textures/xboxControllerLeftShoulder");
            rightShoulder = content.Load<Texture2D>("Textures/xboxControllerRightShoulder");
            pawnWhiteTex = content.Load<Texture2D>("Textures/pawn_white");
            pawnBlackTex = content.Load<Texture2D>("Textures/pawn_black");
            rookWhiteTex = content.Load<Texture2D>("Textures/rook_white");
            rookBlackTex = content.Load<Texture2D>("Textures/rook_black");
            knightWhiteTex = content.Load<Texture2D>("Textures/knight_white");
            knightBlackTex = content.Load<Texture2D>("Textures/knight_black");
            bishopWhiteTex = content.Load<Texture2D>("Textures/bishop_white");
            bishopBlackTex = content.Load<Texture2D>("Textures/bishop_black");
            queenWhiteTex = content.Load<Texture2D>("Textures/queen_white");
            queenBlackTex = content.Load<Texture2D>("Textures/queen_black");
            kingWhiteTex = content.Load<Texture2D>("Textures/king_white");
            kingBlackTex = content.Load<Texture2D>("Textures/king_black");
            kingWhiteCheckTex = content.Load<Texture2D>("Textures/king_white_check");
            kingBlackCheckTex = content.Load<Texture2D>("Textures/king_black_check");
            kingWhiteCheckmateTex = content.Load<Texture2D>("Textures/king_white_checkmate");
            kingBlackCheckmateTex = content.Load<Texture2D>("Textures/king_black_checkmate");
        }

        /// <summary>
        /// Construct a board with the layout and type as provided by the input.
        /// </summary>
        /// <param name="p_Board"></param>
        public Board(Board p_Board)
        {   
            //Lists
            Moves = new List<Move>(p_Board.Moves.Count + (int)p_Board.difficulty);

            // Initialize the variables, table is by default all null
            variant = p_Board.variant;

            switch (variant)
            {
                case GameVariant.Glinsky:
                case GameVariant.McCooey:
                    BoardConstructor.ConstructTilesGlinskiMcCooey(ref tiles);
                    break;
                case GameVariant.Shafran:
                    BoardConstructor.ConstructTilesShafran(ref tiles);
                    break;
            }

            for (int i = 0; i < tiles.Length; i++)
            {
                if (p_Board.tiles[i] != null && p_Board.tiles[i].Piece != PieceType.None)
                {
                    this.tiles[i].Piece = p_Board.tiles[i].Piece;
                    this.tiles[i].Side = p_Board.tiles[i].Side;
                    this.tiles[i].PieceWasPawnOnStartingTile = p_Board.tiles[i].PieceWasPawnOnStartingTile;
                    this.tiles[i].PieceHasMoved = p_Board.tiles[i].PieceHasMoved;
                    if (p_Board.tiles[i].WasEnPassant)
                        this.tiles[i].EnPassantIndex = p_Board.tiles[i].EnPassantIndex;

                    // construct moveable lists
                    for (int x = 0; x < p_Board.tiles[i].AvailableMoves.Count; x++)
                        this.tiles[i].AvailableMoves.Add(this.tiles[(int)p_Board.tiles[i].AvailableMoves[x].IndexInArray]);
                }
            }

            WhiteKing = p_Board.WhiteKing;
            BlackKing = p_Board.BlackKing;
            CanCastleWhiteBishop = p_Board.CanCastleWhiteBishop;
            CanCastleWhiteQueen = p_Board.CanCastleWhiteQueen;
            CanCastleBlackQueen = p_Board.CanCastleBlackQueen;
            CanCastleBlackBishop = p_Board.CanCastleBlackBishop;

            // recreate move history
            for (int i = 0; i < p_Board.Moves.Count; i++)
                this.Moves.Add(p_Board.Moves[i]);

            Score = p_Board.Score;
            CurrentTurn = p_Board.CurrentTurn;
            WhiteCheck = p_Board.WhiteCheck;
            WhiteCheckmate = p_Board.WhiteCheckmate;
            BlackCheck = p_Board.BlackCheck;
            BlackCheckmate = p_Board.BlackCheckmate;
            for (int i = 0; i < p_Board.BoardPositions.Count; i++)
                this.BoardPositions.Add(p_Board.BoardPositions[i]);
            RepeatedMoveCount = p_Board.RepeatedMoveCount;
            FiftyMoveCount = p_Board.FiftyMoveCount;

            numPlayers = p_Board.numPlayers;
            players = new Player[2];
            difficulty = p_Board.difficulty;
        }

        public void Draw(GameTime gameTime, SpriteBatch spriteBatch, int screenWidth, int screenHeight)
        {
            if (this.numPlayers == 2)
            {
                if (CurrentTurn == PieceColor.White)
                {
                    if (players[0].Side == PieceColor.White)
                        curPlayer = players[0];
                    else
                        curPlayer = players[1];
                }
                else
                {
                    if (players[0].Side == PieceColor.Black)
                        curPlayer = players[0];
                    else
                        curPlayer = players[1];
                }
            }
            else
            {
                curPlayer = players[0];
            }


            if (curPlayer.SourceTile != null && !curPlayer.UpgradingPieces)
            {
                // Draw star for selected piece
                if (curPlayer.SourceTile.Piece != PieceType.Pawn)
                {
                    if (curPlayer.SourceTile.Piece == PieceType.King)
                        curPlayer.SourceTile.Position = new Vector3(curPlayer.SourceTile.Position.X, 40, curPlayer.SourceTile.Position.Z);
                    else if (curPlayer.SourceTile.Piece == PieceType.Queen || curPlayer.SourceTile.Piece == PieceType.Bishop)
                        curPlayer.SourceTile.Position = new Vector3(curPlayer.SourceTile.Position.X, 30, curPlayer.SourceTile.Position.Z);
                    else
                        curPlayer.SourceTile.Position = new Vector3(curPlayer.SourceTile.Position.X, 15, curPlayer.SourceTile.Position.Z);
                }
                else
                    curPlayer.SourceTile.Position = new Vector3(curPlayer.SourceTile.Position.X, 0, curPlayer.SourceTile.Position.Z);

                if (curPlayer.Side == PieceColor.White)
                    DrawSupport.DrawModel(diamondWhite, curPlayer.SourceTile.ModelMatrix, diamondWhiteTransforms, curPlayer.PlayerCamera, pieceColor);
                else
                    DrawSupport.DrawModel(diamondBlack, curPlayer.SourceTile.ModelMatrix, diamondBlackTransforms, curPlayer.PlayerCamera, pieceColor);

                curPlayer.SourceTile.Position = new Vector3(curPlayer.SourceTile.Position.X, 0, curPlayer.SourceTile.Position.Z);
            }

            for (int i = 0; i < tiles.Length; i++)
            {
                // Set tile heights/scales
                if (curPlayer.displayAvailable < 2 && curPlayer.SourceTile != null && !curPlayer.UpgradingPieces && (curPlayer.SourceTile.AvailableMoves.Contains(Tiles[i])))
                {
                    curPlayer.SourceTile.Position = new Vector3(curPlayer.SourceTile.Position.X, 0, curPlayer.SourceTile.Position.Z);
                    Tiles[i].Position = new Vector3(Tiles[i].Position.X, 5, Tiles[i].Position.Z);

                    if (curPlayer.displayAvailable == 0)
                    {
                        if (this.OpposingMoves.Contains(Tiles[i].IndexInArray))
                            DrawSupport.DrawModel(tileGrey, Tiles[i].ModelMatrix, tileGrayTransforms, curPlayer.PlayerCamera, tileColorAttackable);
                        else
                            DrawSupport.DrawModel(tileGrey, Tiles[i].ModelMatrix, tileGrayTransforms, curPlayer.PlayerCamera, tileColorMoveable);
                    }
                    else if (curPlayer.displayAvailable == 1)
                    {
                        DrawSupport.DrawModel(tileGrey, Tiles[i].ModelMatrix, tileGrayTransforms, curPlayer.PlayerCamera, tileColorMoveable);
                    }
                }
                else
                {
                    // Draw tiles
                    switch (Tiles[i].color)
                    {
                        case TileColor.Dark:
                            DrawSupport.DrawModel(tileDark, Tiles[i].ModelMatrix, tileDarkTransforms, curPlayer.PlayerCamera, Vector3.Zero);
                            break;
                        case TileColor.Grey:
                            DrawSupport.DrawModel(tileGrey, Tiles[i].ModelMatrix, tileGrayTransforms, curPlayer.PlayerCamera, Vector3.Zero);
                            break;
                        case TileColor.Light:
                            DrawSupport.DrawModel(tileLight, Tiles[i].ModelMatrix, tileLightTransforms, curPlayer.PlayerCamera, Vector3.Zero);
                            break;
                    }
                    Tiles[i].Position = new Vector3(Tiles[i].Position.X, 0, Tiles[i].Position.Z);
                }


                // Set tile tints
                if (Tiles[i] == curPlayer.SelectedTile)
                {
                    if (Tiles[i].Piece != PieceType.None && Tiles[i].Side == curPlayer.Side)
                        currentColor = selectedColor;
                    else
                        currentColor = attackableColor;

                    if (curPlayer.Side == PieceColor.White)
                        DrawSupport.DrawModel(containerWhite, Tiles[i].ModelMatrix, containerWhiteTransforms, curPlayer.PlayerCamera, pieceColor);
                    else
                        DrawSupport.DrawModel(containerBlack, Tiles[i].ModelMatrix, containerBlackTransforms, curPlayer.PlayerCamera, pieceColor);
                }
                else
                    currentColor = pieceColor;

                // Draw models
                switch (Tiles[i].Side)
                {
                    case PieceColor.White:
                        switch (Tiles[i].Piece)
                        {
                            case PieceType.Pawn:
                                DrawSupport.DrawModel(pawnWhite, Tiles[i].ModelMatrix, pawnWhiteTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.Rook:
                                DrawSupport.DrawModel(rookWhite, Tiles[i].ModelMatrix, rookWhiteTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.Knight:
                                DrawSupport.DrawModel(knightWhite, Tiles[i].ModelMatrix, knightWhiteTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.Bishop:
                                DrawSupport.DrawModel(bishopWhite, Tiles[i].ModelMatrix, bishopWhiteTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.Queen:
                                DrawSupport.DrawModel(queenWhite, Tiles[i].ModelMatrix, queenWhiteTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.King:
                                DrawSupport.DrawModel(kingWhite, Tiles[i].ModelMatrix, kingWhiteTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                        }
                        break;
                    case PieceColor.Black:
                        switch (Tiles[i].Piece)
                        {
                            case PieceType.Pawn:
                                DrawSupport.DrawModel(pawnBlack, Tiles[i].ModelMatrix, pawnBlackTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.Rook:
                                DrawSupport.DrawModel(rookBlack, Tiles[i].ModelMatrix, rookBlackTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.Knight:
                                DrawSupport.DrawModel(knightBlack, Tiles[i].ModelMatrix, knightBlackTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.Bishop:
                                DrawSupport.DrawModel(bishopBlack, Tiles[i].ModelMatrix, bishopBlackTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.Queen:
                                DrawSupport.DrawModel(queenBlack, Tiles[i].ModelMatrix, queenBlackTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                            case PieceType.King:
                                DrawSupport.DrawModel(kingBlack, Tiles[i].ModelMatrix, kingBlackTransforms, curPlayer.PlayerCamera, currentColor);
                                break;
                        }
                        break;
                }
            }

            // todo clean up all the extra declarations, single declare when possible
            // Draw the captured pieces
            int x = 0;
            int y = 0;
#if XBOX
            x = screenWidth / 10;
            y = screenHeight / 10;
#endif
            int dim = 32;

            spriteBatch.Begin();

            // Draw fifty move and repeated move
            if ((FiftyMoveCount > 49 || RepeatedMoveCount > 1) && curPlayer.displayMode == 0)
            {
                if (FiftyMoveCount > 49 && RepeatedMoveCount < 2)
                {
                    x = (int)spriteFontSmall.MeasureString("Fifty Move: " + FiftyMoveCount).X;
                    spriteBatch.Draw(gradient, new Rectangle((screenWidth / 2) - (x / 2) - 20, screenHeight - y - 35, x + 20, 35), new Color(0.5f, 0.5f, 0.5f, 0.5f));
                    spriteBatch.DrawString(spriteFontSmall, "Fifty Move: " + FiftyMoveCount, new Vector2((screenWidth / 2) - (x / 2) - 10, screenHeight - y - 35), Color.White);
                }
                else if (FiftyMoveCount < 50 && RepeatedMoveCount > 1)
                {
                    x = (int)spriteFontSmall.MeasureString("Threefold Repetition: " + RepeatedMoveCount).X;
                    spriteBatch.Draw(gradient, new Rectangle((screenWidth / 2) - (x / 2) - 20, screenHeight - y - 35, x + 20, 35), new Color(0.5f, 0.5f, 0.5f, 0.5f));
                    spriteBatch.DrawString(spriteFontSmall, "Threefold Repetition: " + RepeatedMoveCount, new Vector2((screenWidth / 2) - (x / 2) - 10, screenHeight - y - 35), Color.White);
                }
                else
                {
                    // length of both + 5 px on each end + 10 px in middle
                    x = (int)spriteFontSmall.MeasureString("Fifty Move: " + FiftyMoveCount + "   ").X + (int)spriteFontSmall.MeasureString("Threefold Repetition: " + RepeatedMoveCount).X + 20;
                    spriteBatch.Draw(gradient, new Rectangle((screenWidth / 2) - (x / 2) - 20, screenHeight - y - 35, x + 20, 35), new Color(0.5f, 0.5f, 0.5f, 0.5f));
                    spriteBatch.DrawString(spriteFontSmall, "Fifty Move: " + FiftyMoveCount + "   " + "Threefold Repetition: " + RepeatedMoveCount, new Vector2((screenWidth / 2) - (x / 2) - 5, screenHeight - y - 35), Color.White);
                }
            }

            x = y = 20;
#if XBOX
            x = (screenWidth / 10) + 20;
            y = (screenHeight / 10) + 20;
#endif
            // draw the move history
            if (Stalemate)
            {
                spriteBatch.Draw(gradient, new Rectangle((screenWidth / 2) - (dim * 4), ((y + dim) * 2) - 10, dim * 8, y + dim), new Color(0.5f, 0.5f, 0.5f, 0.5f));
                spriteBatch.DrawString(spriteFont, "Stalemate", new Vector2((screenWidth / 2) - ((int)spriteFont.MeasureString("Stalemate").X / 2), ((y + dim) * 2) - 5), Color.White);
            }
            if (this.Moves.Count > 0 && curPlayer.displayMode < 2)
            {
                spriteBatch.Draw(gradient, new Rectangle((screenWidth / 2) - (dim * 5), y - 10, dim * 10, 20 + dim), new Color(0.5f, 0.5f, 0.5f, 0.5f));
                int r1 = (int)tiles[this.Moves[this.Moves.Count - 1].SourceTileIndex].rank + 1;
                int r2 = (int)tiles[this.Moves[this.Moves.Count - 1].DestTileIndex].rank + 1;
                string drawString = tiles[this.Moves[this.Moves.Count - 1].SourceTileIndex].file.ToString() + r1 + " to " + tiles[this.Moves[this.Moves.Count - 1].DestTileIndex].file.ToString() + r2;
                x = (screenWidth / 2) + ((int)spriteFont.MeasureString(drawString).X / 2);

                switch (this.Moves[this.Moves.Count - 1].SourceTileSide)
                {
                    case PieceColor.White:
                        switch (this.Moves[this.Moves.Count - 1].SourceTilePiece)
                        {
                            case PieceType.Pawn:
                                spriteBatch.Draw(pawnWhiteTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.Rook:
                                spriteBatch.Draw(rookWhiteTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.Knight:
                                spriteBatch.Draw(knightWhiteTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.Bishop:
                                spriteBatch.Draw(bishopWhiteTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.Queen:
                                spriteBatch.Draw(queenWhiteTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.King:
                                spriteBatch.Draw(kingWhiteTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                        }

                        switch (this.Moves[this.Moves.Count - 1].DestTilePiece)
                        {
                            case PieceType.Pawn:
                                spriteBatch.Draw(pawnBlackTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.Rook:
                                spriteBatch.Draw(rookBlackTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.Knight:
                                spriteBatch.Draw(knightBlackTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.Bishop:
                                spriteBatch.Draw(bishopBlackTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.Queen:
                                spriteBatch.Draw(queenBlackTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.King:
                                spriteBatch.Draw(kingBlackTex, new Rectangle(x, y, dim, dim), Color.White); break;
                        }

                        if (Moves[Moves.Count - 1].DestTilePiece != PieceType.None)
                        {
                            if (BlackCheckmate)
                                spriteBatch.Draw(kingBlackCheckmateTex, new Rectangle(x + dim, y, dim, dim), Color.White);
                            else if (BlackCheck)
                                spriteBatch.Draw(kingBlackCheckTex, new Rectangle(x + dim, y, dim, dim), Color.White);
                        }
                        else
                        {
                            if (BlackCheckmate)
                                spriteBatch.Draw(kingBlackCheckmateTex, new Rectangle(x, y, dim, dim), Color.White);
                            else if (BlackCheck)
                                spriteBatch.Draw(kingBlackCheckTex, new Rectangle(x, y, dim, dim), Color.White);
                        }
                        break;
                    case PieceColor.Black:
                        switch (this.Moves[this.Moves.Count - 1].SourceTilePiece)
                        {
                            case PieceType.Pawn:
                                spriteBatch.Draw(pawnBlackTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.Rook:
                                spriteBatch.Draw(rookBlackTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.Knight:
                                spriteBatch.Draw(knightBlackTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.Bishop:
                                spriteBatch.Draw(bishopBlackTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.Queen:
                                spriteBatch.Draw(queenBlackTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                            case PieceType.King:
                                spriteBatch.Draw(kingBlackTex, new Rectangle((screenWidth / 2) - (dim) - ((int)spriteFont.MeasureString(drawString).X / 2), y, dim, dim), Color.White); break;
                        }

                        switch (this.Moves[this.Moves.Count - 1].DestTilePiece)
                        {
                            case PieceType.Pawn:
                                spriteBatch.Draw(pawnWhiteTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.Rook:
                                spriteBatch.Draw(rookWhiteTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.Knight:
                                spriteBatch.Draw(knightWhiteTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.Bishop:
                                spriteBatch.Draw(bishopWhiteTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.Queen:
                                spriteBatch.Draw(queenWhiteTex, new Rectangle(x, y, dim, dim), Color.White); break;
                            case PieceType.King:
                                spriteBatch.Draw(kingWhiteTex, new Rectangle(x, y, dim, dim), Color.White); break;
                        }

                        if (Moves[Moves.Count - 1].DestTilePiece != PieceType.None)
                        {
                            if (WhiteCheckmate)
                                spriteBatch.Draw(kingWhiteCheckmateTex, new Rectangle(x + dim, y, dim, dim), Color.White);
                            else if (WhiteCheck)
                                spriteBatch.Draw(kingWhiteCheckTex, new Rectangle(x + dim, y, dim, dim), Color.White);
                        }
                        else
                        {
                            if (WhiteCheckmate)
                                spriteBatch.Draw(kingWhiteCheckmateTex, new Rectangle(x, y, dim, dim), Color.White);
                            else if (WhiteCheck)
                                spriteBatch.Draw(kingWhiteCheckTex, new Rectangle(x, y, dim, dim), Color.White);
                        }
                        break;
                }

                spriteBatch.DrawString(spriteFont, drawString, new Vector2((screenWidth / 2) - ((int)spriteFont.MeasureString(drawString).X / 2), y - 5), Color.White);
            }

            // draw dead pieces
            x = 20;
            y = 20;
#if XBOX
            x = (screenWidth / 10) + 20;
            y = (screenHeight / 10) + 20;
#endif
            for (int i = 0; i < WhitePiecesDead.Count; i++)
            {
                if (i > 0 && i % 3 == 0)
                {
                    y += dim;
                    x = 20;
#if XBOX
            x = (screenWidth / 10) + 20;
#endif
                }

                switch (WhitePiecesDead[i])
                {
                    case PieceType.Pawn:
                        spriteBatch.Draw(pawnWhiteTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                    case PieceType.Rook:
                        spriteBatch.Draw(rookWhiteTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                    case PieceType.Knight:
                        spriteBatch.Draw(knightWhiteTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                    case PieceType.Bishop:
                        spriteBatch.Draw(bishopWhiteTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                    case PieceType.Queen:
                        spriteBatch.Draw(queenWhiteTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                }

                x += dim;
            }

            // draw ai indicator
            if (isPlayer2AI && player1Color == PieceColor.White)
            {
                x = dim + 5;
                y += (dim + 10);
#if XBOX
                x = (screenWidth / 10) + dim + 5;
#endif
                // Pulsate the size of the icon.
                double time = gameTime.TotalGameTime.TotalSeconds;
                float pulsate = (float)Math.Sin(time * 6) + 1;
                // float scale = 1 + pulsate * 0.05f * thinkingFade;
                float scale = 1 - pulsate * 0.5f * thinkingFade;

                spriteBatch.Draw(ai, new Rectangle(x, y, 64, 64), Color.White * scale);
            }

            y = 20;
            x = screenWidth - (dim * 3) - 20;
#if XBOX
            x = screenWidth - (dim * 3) - (screenWidth / 10) - 20;
            y = (screenHeight / 10) + 20;
#endif
            for (int i = 0; i < BlackPiecesDead.Count; i++)
            {
                if (i > 0 && i % 3 == 0)
                {
                    y += dim;
                    x = screenWidth - (dim * 3) - 20;
#if XBOX
            x = screenWidth - (dim * 3) - (screenWidth / 10) - 20;
#endif
                }

                switch (BlackPiecesDead[i])
                {
                    case PieceType.Pawn:
                        spriteBatch.Draw(pawnBlackTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                    case PieceType.Rook:
                        spriteBatch.Draw(rookBlackTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                    case PieceType.Knight:
                        spriteBatch.Draw(knightBlackTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                    case PieceType.Bishop:
                        spriteBatch.Draw(bishopBlackTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                    case PieceType.Queen:
                        spriteBatch.Draw(queenBlackTex, new Rectangle(x, y, dim, dim), Color.White);
                        break;
                }

                x += dim;
            }

            // draw ai indicator
            if (isPlayer2AI && player1Color == PieceColor.Black)
            {
                x = screenWidth - 64 - dim;
                y += (dim + 10);
#if XBOX
                x = screenWidth - (screenWidth / 10) - 64 - dim;
#endif
                // Pulsate the size of the icon.
                double time = gameTime.TotalGameTime.TotalSeconds;
                float pulsate = (float)Math.Sin(time * 6) + 1;
                // float scale = 1 + pulsate * 0.05f * thinkingFade;
                float scale = 1 - pulsate * 0.5f * thinkingFade;

                spriteBatch.Draw(ai, new Rectangle(x, y, 64, 64), Color.White * scale);
            }

            // draw upgrade options
            if (curPlayer.UpgradingPieces)
            {
                dim = 64;                       // Draw 64 x 64
                x = (screenWidth / 7);          // Draw in 1/7 increments
                y = (screenHeight / 7);

                spriteBatch.Draw(gradient, new Rectangle(x * 2, y, x * 3, y * 5), new Color(0.5f, 0.5f, 0.5f, 0.5f));

                spriteBatch.Draw(aButton, new Rectangle((x * 3) - 32, (y * 5) - 32, dim, dim), Color.White);
                spriteBatch.Draw(bButton, new Rectangle((x * 4) - 32, (y * 4) - 32, dim, dim), Color.White);
                spriteBatch.Draw(xButton, new Rectangle((x * 3) - 32, (y * 3) - 32, dim, dim), Color.White);
                spriteBatch.Draw(yButton, new Rectangle((x * 4) - 32, (y * 2) - 32, dim, dim), Color.White);

                if (curPlayer.Side == PieceColor.White)
                {
                    spriteBatch.Draw(queenWhiteTex, new Rectangle((x * 3) - 32 - dim, (y * 5) - 32, dim, dim), Color.White);
                    spriteBatch.Draw(bishopWhiteTex, new Rectangle((x * 4) - 32 - dim, (y * 4) - 32, dim, dim), Color.White);
                    spriteBatch.Draw(rookWhiteTex, new Rectangle((x * 3) - 32 - dim, (y * 3) - 32, dim, dim), Color.White);
                    spriteBatch.Draw(knightWhiteTex, new Rectangle((x * 4) - 32 - dim, (y * 2) - 32, dim, dim), Color.White);
                }
                else
                {
                    spriteBatch.Draw(queenBlackTex, new Rectangle((x * 3) - 32 - dim, (y * 5) - 32, dim, dim), Color.White);
                    spriteBatch.Draw(bishopBlackTex, new Rectangle((x * 4) - 32 - dim, (y * 4) - 32, dim, dim), Color.White);
                    spriteBatch.Draw(rookBlackTex, new Rectangle((x * 3) - 32 - dim, (y * 3) - 32, dim, dim), Color.White);
                    spriteBatch.Draw(knightBlackTex, new Rectangle((x * 4) - 32 - dim, (y * 2) - 32, dim, dim), Color.White);
                }
            }

            x = y = 20;
#if XBOX
            x = (screenWidth / 10) + 20;
            y = (screenHeight / 10) + 20;
#endif
            // Draw restart options
            if (Stalemate || WhiteCheckmate || BlackCheckmate || FiftyMoveCount >= 100 || RepeatedMoveCount >= 3)
            {
                spriteBatch.Draw(aButton, new Rectangle(x, screenHeight - y - 64, 64, 64), Color.White);
                spriteBatch.Draw(bButton, new Rectangle(screenWidth - x - 64, screenHeight - y - 64, 64, 64), Color.White);
                spriteBatch.DrawString(spriteFontMed, "Restart", new Vector2(x + 64, screenHeight - y - 64), Color.White);
                spriteBatch.DrawString(spriteFontMed, "Quit", new Vector2(screenWidth - x - 64 - (int)spriteFontMed.MeasureString("Quit").X, screenHeight - y - 64), Color.White);
            }
            else
            {
                if (curPlayer.Side == this.CurrentTurn && !isAIThinking && !curPlayer.UpgradingPieces)
                {
                    if (curPlayer.SourceTile != null)
                    {
                        if (curPlayer.SelectedTile == curPlayer.SourceTile)
                        {
                            spriteBatch.Draw(aButton, new Rectangle(x, screenHeight - y - 32, 32, 32), Color.White);
                            spriteBatch.DrawString(spriteFont, "Deselect", new Vector2(x + 52, screenHeight - y - 32), Color.White);
                        }
                        else if (curPlayer.SelectedTile.Piece != PieceType.None && curPlayer.SelectedTile.Side != curPlayer.Side)
                        {
                            spriteBatch.Draw(aButton, new Rectangle(x, screenHeight - y - 32, 32, 32), Color.White);
                            spriteBatch.DrawString(spriteFont, "Capture", new Vector2(x + 52, screenHeight - y - 32), Color.White);
                        }
                        else if (curPlayer.SourceTile.AvailableMoves.Contains(curPlayer.SelectedTile))
                        {
                            spriteBatch.Draw(aButton, new Rectangle(x, screenHeight - y - 32, 32, 32), Color.White);
                            spriteBatch.DrawString(spriteFont, "Move", new Vector2(x + 52, screenHeight - y - 32), Color.White);
                        }

                        spriteBatch.Draw(bButton, new Rectangle(screenWidth - x - 32, screenHeight - y - 32, 32, 32), Color.White);
                        spriteBatch.DrawString(spriteFont, "Deselect", new Vector2(screenWidth - x - 52 - (int)spriteFont.MeasureString("Deselect").X, screenHeight - y - 32), Color.White);
                    }
                    else if (curPlayer.SelectedTile.Piece != PieceType.None && curPlayer.SelectedTile.Side == curPlayer.Side)
                    {
                        spriteBatch.Draw(aButton, new Rectangle(x, screenHeight - y - 32, 32, 32), Color.White);
                        spriteBatch.DrawString(spriteFont, "Select", new Vector2(x + 52, screenHeight - y - 32), Color.White);
                    }

                    // Draw castling
                    switch (CurrentTurn)
                    {
                        case PieceColor.White:
                            if (CanCastleWhiteQueen == 2)       // Castle queen long
                            {
                                spriteBatch.Draw(leftShoulder, new Rectangle(x, screenHeight - y - 168, 64, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Long", new Vector2(96 + x, screenHeight - y - 168), Color.White);

                                spriteBatch.Draw(xButton, new Rectangle(x, screenHeight - y - 116, 32, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Short", new Vector2(64 + x, screenHeight - y - 116), Color.White);
                            }
                            else if (CanCastleWhiteQueen == 1)  // Castle queen short
                            {
                                spriteBatch.Draw(xButton, new Rectangle(x, screenHeight - y - 116, 32, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Short", new Vector2(64 + x, screenHeight - y - 116), Color.White);
                            }

                            if (CanCastleWhiteBishop == 2)      // Castle bishop long
                            {
                                spriteBatch.Draw(rightShoulder, new Rectangle(screenWidth - x - 64, screenHeight - y - 168, 64, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Long", new Vector2(screenWidth - x - 84 - (int)spriteFont.MeasureString("Castle Long").X, screenHeight - y - 168), Color.White);

                                spriteBatch.Draw(yButton, new Rectangle(screenWidth - x - 32, screenHeight - y - 116, 32, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Short", new Vector2(screenWidth - x - 52 - (int)spriteFont.MeasureString("Castle Short").X, screenHeight - y - 116), Color.White);
                            }
                            else if (CanCastleWhiteBishop == 1) // Castle bishop short
                            {
                                spriteBatch.Draw(yButton, new Rectangle(screenWidth - x - 32, screenHeight - y - 116, 32, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Short", new Vector2(screenWidth - x - 52 - (int)spriteFont.MeasureString("Castle Short").X, screenHeight - y - 116), Color.White);
                            }
                            break;
                        case PieceColor.Black:
                            if (CanCastleBlackQueen == 2)       // Castle queen long
                            {
                                spriteBatch.Draw(leftShoulder, new Rectangle(x, screenHeight - y - 168, 64, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Long", new Vector2(96 + x, screenHeight - y - 168), Color.White);

                                spriteBatch.Draw(xButton, new Rectangle(x, screenHeight - y - 116, 32, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Short", new Vector2(64 + x, screenHeight - y - 116), Color.White);
                            }
                            else if (CanCastleBlackQueen == 1)  // Castle queen short
                            {
                                spriteBatch.Draw(xButton, new Rectangle(x, screenHeight - y - 116, 32, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Short", new Vector2(64 + x, screenHeight - y - 116), Color.White);
                            }

                            if (CanCastleBlackBishop == 2)      // Castle bishop long
                            {
                                spriteBatch.Draw(rightShoulder, new Rectangle(screenWidth - x - 64, screenHeight - y - 168, 64, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Long", new Vector2(screenWidth - x - 84 - (int)spriteFont.MeasureString("Castle Long").X, screenHeight - y - 168), Color.White);

                                spriteBatch.Draw(yButton, new Rectangle(screenWidth - x - 32, screenHeight - y - 116, 32, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Short", new Vector2(screenWidth - x - 52 - (int)spriteFont.MeasureString("Castle Short").X, screenHeight - y - 116), Color.White);
                            }
                            else if (CanCastleBlackBishop == 1) // Castle bishop short
                            {
                                spriteBatch.Draw(yButton, new Rectangle(screenWidth - x - 32, screenHeight - y - 116, 32, 32), Color.White);
                                spriteBatch.DrawString(spriteFont, "Castle Short", new Vector2(screenWidth - x - 52 - (int)spriteFont.MeasureString("Castle Short").X, screenHeight - y - 116), Color.White);
                            }
                            break;
                    }
                }
            }

            spriteBatch.End();
        }

        public void Update(GameTime gameTime)
        {
            // When changing thinking status, entries gradually fade between
            // their selected and deselected appearance, rather than instantly
            // popping to the new state.
            float fadeSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 4;

            if (isAIThinking)
                thinkingFade = Math.Min(thinkingFade + fadeSpeed, 1);
            else
                thinkingFade = Math.Max(thinkingFade - fadeSpeed, 0);

            if (!BlackCheckmate && !WhiteCheckmate && !Stalemate && FiftyMoveCount < 100 && RepeatedMoveCount < 3)
            {
                for (int i = 0; i < players.Length; i++)
                {
                    if (this.CurrentTurn == players[i].Side && !isAIThinking)
                    {
                        players[i].Update(this, gameTime);
                        return;
                    }
                    else if (isAIThinking)  // this works in tandem with handleinput, allows players to update their camera
                    {
                        players[0].Update(this, gameTime);
                    }
                }
            }
        }

        public void HandleInput(InputState inputState, GameTime gameTime)
        {
            for (int i = 0; i < players.Length; i++)
            {
                // only current player in two player games can execute OR in single player, only rotate commands can be given.
                // first, check current player
                if (this.CurrentTurn == players[i].Side)
                {
                    players[i].HandleInput(inputState, gameTime);
                    // If we don't exit here, the "newkeypress" on a keyboard is shared for all players, selecting/deselecting.
                    return; // quit here to prevent the second player's piece from being selected on start, by handling a keyboard "enter", as the keyboard shares controls
                }
                else if (isAIThinking)
                {
                    // check player1 control for rotate only: playerIndices[0]
                    // this is an ugly hack
                    if (inputState.IsNewKeyPress(Keys.OemPeriod, players[0].playerIndex) || inputState.IsNewButtonPress(Buttons.RightThumbstickRight, players[0].playerIndex) ||
                        inputState.IsNewKeyPressUp(Keys.OemPeriod, players[0].playerIndex) || inputState.IsNewButtonPressUp(Buttons.RightThumbstickRight, players[0].playerIndex) ||
                        inputState.IsNewKeyPress(Keys.OemComma, players[0].playerIndex) || inputState.IsNewButtonPress(Buttons.RightThumbstickLeft, players[0].playerIndex) ||
                        inputState.IsNewKeyPressUp(Keys.OemComma, players[0].playerIndex) || inputState.IsNewButtonPress(Buttons.RightThumbstickLeft, players[0].playerIndex) ||
                        inputState.IsNewKeyPress(Keys.L, players[0].playerIndex) || inputState.IsNewButtonPressUp(Buttons.RightThumbstickUp, players[0].playerIndex) ||
                        inputState.IsNewKeyPressUp(Keys.L, players[0].playerIndex) || inputState.IsNewButtonPress(Buttons.RightThumbstickUp, players[0].playerIndex))
                    {
                        players[0].HandleInput(inputState, gameTime);
                    }
                }
            }
        }
    }
}